#ifndef __PVMDEVICEINTERFACE_H__
#define __PVMDEVICEINTERFACE_H__

//this interface is used just to order drivers internals and can be skipped (but it recomended to use it)

#include "pvm/pvmapi.h"
#include "lib/3d/pvm3dinterface.h"

class IPVMVoice;
class IPVMDriverBase;

class IPVMDeviceBase
{
protected:
	IPVMDeviceBase() {};
public:
	virtual ~IPVMDeviceBase() {};

	virtual pvm_uint32 GetDeviceType() = 0;
	virtual void DeviceClose() = 0;
	virtual pvm_bool DeviceOpened() = 0;

	virtual void Suspend() = 0;
	virtual pvm_bool IsSuspended() = 0;
	virtual void Resume() = 0;

	virtual pvm_bool SetOption(const pvm_char* optionName, void* param, pvm_uint32 paramSize) = 0;
	virtual pvm_bool GetOption(const pvm_char* optionName, void* param, pvm_uint32* paramSize) = 0;

	virtual pvm_int32 GetCPUUsage() = 0; //returns CPU usage in percents

	virtual pvm_uint32 GetChanelsNum() = 0;
	virtual pvm_uint32 GetBitsPerSample() = 0;
	virtual pvm_uint32 GetSamplesPerSecond() = 0;

	virtual IPVMDriverBase* GetDriver() = 0;
};

class IPVMDeviceOutSimple : public IPVMDeviceBase
{
protected:
	IPVMDeviceOutSimple() {};
public:
	virtual ~IPVMDeviceOutSimple() {};

	virtual void DeviceNotify() = 0;

	virtual void SetBufferLengthMs(pvm_uint32 bufferSize) = 0;
	virtual pvm_uint32 GetBufferRealLengthMs() = 0;
};


class IPVMDeviceOut : public IPVMDeviceOutSimple
{
protected:
	IPVMDeviceOut() {};
public:
	virtual ~IPVMDeviceOut() {};

	virtual void SetMixingVolume(pvm_uint32 volume) = 0;
	virtual pvm_uint32 GetMixingVolume() = 0;

	virtual pvm_int32 PlayVoice(IPVMVoice* voice, pvm_int32 voiceNumAndFlags, TVoiceCallbackProc callbackProc, pvm_uint32 callbackPeriod, void* calbackParam) = 0;
	virtual void StopVoice(pvm_uint32 voiceSlot) = 0;
	virtual pvm_bool IsVoiceFree(pvm_uint32 voiceSlot) = 0;

	virtual pvm_bool SetRate(pvm_uint32 voiceSlot, pvm_int32 value) = 0;
	virtual pvm_bool SetPanning(pvm_uint32 voiceSlot, pvm_int32 value) = 0;
	virtual pvm_bool SetVolume(pvm_uint32 voiceSlot, pvm_int32 value) = 0;
	virtual pvm_bool SetLoopCount(pvm_uint32 voiceSlot, pvm_int32 value) = 0;
	virtual pvm_bool SetLoopInSamples(pvm_uint32 voiceSlot, pvm_int64 loopFrom, pvm_int64 loopTo) = 0;
	virtual pvm_bool SetPause(pvm_uint32 voiceSlot, pvm_bool value) = 0;
	virtual pvm_bool SetRenderSilentVoice(pvm_uint32 voiceSlot, pvm_bool value) = 0;

	virtual pvm_bool GetRate(pvm_uint32 voiceSlot, pvm_int32& value) = 0;
	virtual pvm_bool GetPanning(pvm_uint32 voiceSlot, pvm_int32& value) = 0;
	virtual pvm_bool GetVolume(pvm_uint32 voiceSlot, pvm_int32& value) = 0;
	virtual pvm_bool GetLoopCount(pvm_uint32 voiceSlot, pvm_int32& value) = 0;
	virtual pvm_bool GetLoopInSamples(pvm_uint32 voiceSlot, pvm_int64 &loopFrom, pvm_int64 &loopTo) = 0;
	virtual pvm_bool GetLoopInMS(pvm_uint32 voiceSlot, pvm_int32 &loopFrom, pvm_int32 &loopTo) = 0;
	virtual pvm_bool GetPause(pvm_uint32 voiceSlot, pvm_bool& value) = 0;
	virtual pvm_bool GetRenderSilentVoice(pvm_uint32 voiceSlot, pvm_bool& value) = 0;

	virtual pvm_bool SetPositionMS(pvm_uint32 voiceSlot, pvm_int32 value) = 0;
	virtual pvm_bool GetPositionMS(pvm_uint32 voiceSlot, pvm_int32& value) = 0;

	virtual pvm_bool SetVoiceOption(pvm_uint32 voiceSlot, const pvm_char* optionName, void* param, pvm_uint32 paramSize) = 0;
	virtual pvm_bool GetVoiceOption(pvm_uint32 voiceSlot, const pvm_char* optionName, void* param, pvm_uint32* paramSize) = 0;

	virtual pvm_uint32 GetMaxVoices() = 0;

	virtual pvm_bool BeginBatchParams() = 0;
	virtual void EndBatchParams() = 0;

	virtual pvm_bool SetPanningVolumeRate(pvm_uint32 chanelNum, pvm_int32 panning, pvm_int32 volume, pvm_int32 rate) = 0;

	//3d
	virtual pvm_uint32 Get3dSupportFlags() = 0;
	virtual pvm_bool Choose3dInterface(pvm_uint32 realizationType) = 0;
	virtual IPVM3DInterface* Get3dInterface() = 0;
};

class IPVMDeviceOutSimpleWaveSource
{
protected:
	IPVMDeviceOutSimpleWaveSource() {};
public:
	virtual ~IPVMDeviceOutSimpleWaveSource() {};

	virtual pvm_bool IsInitialized() = 0;
	virtual void ResizeRenderBuffer(pvm_uint32 bufferSizeInBytes) = 0;
	virtual pvm_uint32 GetRenderBufferSizeInBytes() = 0;
	virtual pvm_bool HasMoreData() = 0;
	virtual pvm_uint32 FillBuffer(void * buffer, pvm_uint32 bufferSizeInSamples) = 0;

	virtual void OnIdle() = 0;
	virtual void SetForceProcessingOnIdle(pvm_bool flag) = 0;
};

#endif

